package org.jwt.oauth.config;

import java.util.List;

import org.jwt.oauth.constant.ConstantAttribute;
import org.jwt.oauth.filter.FusionLimitAddressFilter;
import org.jwt.oauth.handler.FusionLoginFailureHandler;
import org.jwt.oauth.handler.FusionLoginSuccessHandler;
import org.jwt.oauth.password.FusionPasswordEncoder;
import org.jwt.oauth.properties.FusionTokenProperties;
import org.jwt.oauth.tools.ConcurrentTools;
import org.jwt.oauth.tools.NotLoginAuthUrlTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class FusionSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private FusionLoginSuccessHandler loginSuccessHandler;
	@Autowired
	private FusionLoginFailureHandler loginFailureHandler;
	@Autowired
	private UserDetailsService userDetailsService;
	@Autowired
	private FusionTokenProperties tokenConfigProperties;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		//限制使用接口的拦截器
		FusionLimitAddressFilter fusionLimitAddressFilter = new FusionLimitAddressFilter();
		fusionLimitAddressFilter.setFusionTokenProperties(tokenConfigProperties);
		http
		//在认证之前验证接口是否可以访问
		.addFilterBefore(fusionLimitAddressFilter, UsernamePasswordAuthenticationFilter.class)
		// 设置表单登陆
		.formLogin()
		// 设置登录页（rest风格设置错误的登录页）
		.loginPage(tokenConfigProperties.getLoginErrorUrl())
		// 登陆的方法
		.loginProcessingUrl(tokenConfigProperties.getUserLoginUrl())
		// 登陆成功之后需要处理的方法
		.successHandler(loginSuccessHandler)
		// 登陆失败之后需要处理的方法
		.failureHandler(loginFailureHandler)
		//登陆的实现方法
		.and().userDetailsService(userDetailsService);
		// 设置请求拦截
		ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests = http
				.authorizeRequests();
		String[] noRelease = tokenConfigProperties.getNoRelease();
		if (noRelease != null && noRelease.length > 0) {
			for (String noReleaseUrl : noRelease) {
				if (noReleaseUrl != null && !noReleaseUrl.equalsIgnoreCase(ConstantAttribute.NULL) && noReleaseUrl.length() > 0) {
					authorizeRequests.antMatchers(noReleaseUrl).permitAll();
				}
			}
		}
		List<String> notAuthUrlList = NotLoginAuthUrlTools.getNotAuthUrlList(tokenConfigProperties.getMethodsPackage());
		if(notAuthUrlList!=null && notAuthUrlList.size() > 0) {
			for (String notAuthUrl : notAuthUrlList) {
				authorizeRequests.antMatchers(notAuthUrl).permitAll();
			}
			ConcurrentTools.getConcurrentHashMap().put(ConstantAttribute.NOT_AUTH_URL_LIST,notAuthUrlList);
		}
		authorizeRequests.antMatchers(tokenConfigProperties.getUserLoginUrl()).permitAll();
		authorizeRequests.antMatchers(tokenConfigProperties.getLoginErrorUrl()).permitAll();
		authorizeRequests.antMatchers(tokenConfigProperties.getDefaultExithUrl()).permitAll();
		authorizeRequests.antMatchers(tokenConfigProperties.getDefaultRefreshUrl()).permitAll();
		authorizeRequests.antMatchers(tokenConfigProperties.getDefaultLoginUrl()).permitAll();
		authorizeRequests.antMatchers(HttpMethod.OPTIONS).permitAll();
		// 设置拦截所有的请求
		authorizeRequests.anyRequest().authenticated().and().csrf().disable();
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new FusionPasswordEncoder();
	}

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}
}
